﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Tables;
using System.Security;

namespace ConfigLibrary
{
	/// <summary>
	/// Configuration file object
	/// </summary>
	[Serializable]
	public partial class Config
	{
		#region Private
		private _mailhost mailhost;
		private _datahost datahost;
		private _filemonitor mon;
		private _sqlhost sql;
        private _eddshost edds;
        private _qbhost qb;
		private string _configfile;
		private StringTable table;
		private Offsets offsets;

		#endregion

		public Config ()
		{
			table = new StringTable (512);
		}

		#region Public Properties
		public const string Version = "config 1.5";
		
		public string ConfigFilePath {
			get { return _configfile; }
			set { _configfile = value; }
		}

		public string MailHost
		{ get { return mailhost.hostname; } }

		public string MailUser
		{ get { return mailhost.loginaccount; } }

		public string MailPass
		{ get { return mailhost.password; } }

		public int MailPort
		{ get { return mailhost.port; } }

		public string MonitorFolderPath
		{ get { return mon.monitorpath; } }

		public string WriteFolderPath
		{ get { return mon.writepath; } }

		public string SqlHost
		{ get { return sql.hostname; } }

		public string SqlUser
		{ get { return sql.username; } }

		public string SqlPass
		{ get { return sql.password; } }

		public string SqlDatabase
		{ get { return sql.database; } }
		
		public int SqlPort
		{ get { return sql.port; } }

        public string EddsUser
        { get { return edds.username; } }

        public string EddsPass
        { get { return edds.password; } }

        public string QbUser
        { get { return qb.username; } }

        public string QbPass
        { get { return qb.password; } }
        
		public string DataHost
		{ get { return datahost.hostname; } }

		public int ServerPort
		{ get { return datahost.server_port; } }

		public int ClientPort
		{ get { return datahost.client_port; } }

		#endregion

		#region Fill Data

		/// <summary>
		/// Enters all of the required data for the Mail Server
		/// </summary>
		/// <param name="HostName">Mail server name</param>
		/// <param name="LoginName">The login name to use</param>
		/// <param name="Password">The password to use, enter in as plain text</param>
		/// <param name="Port">the port to connect to the mail server.  IMAP is typically 25</param>
		public void AddMailInfo (string HostName, string LoginName, string Password, int Port)
		{
			mailhost.hostname = HostName;
			mailhost.loginaccount = LoginName;
			mailhost.password = Password;
			mailhost.port = Port;
		}

		/// <summary>
		/// Enters info for the TCP data server.  Not Yet Implemented
		/// </summary>
		/// <param name="HostName">The remote Server host to connect</param>
		/// <param name="Port">The remote port</param>
		public void AddDataInfo (string HostName, int ServerPort, int ClientPort)
		{

			datahost.hostname = HostName;
			datahost.server_port = ServerPort;
			datahost.client_port = ClientPort;
		}

		/// <summary>
		/// Enters info for the file watchers
		/// </summary>
		/// <param name="MonitorPath">Folder path to watch for changes, can not be null</param>
		/// <param name="WritePath">Folder path to write logs when monitored folders change, can be null</param>
		public void AddFileMonitorPaths (string MonitorPath, string WritePath)
		{

			if (MonitorPath == null)
				throw new ArgumentNullException ();
			mon.monitorpath = MonitorPath;
			mon.writepath = WritePath;
		}

		/// <summary>
		/// Enters info to connect to a MySql server
		/// </summary>
		/// <param name="Host"></param>
		/// <param name="Username"></param>
		/// <param name="Password"></param>
		/// <param name="Database"></param>
		public void AddSqlInfo (string Host, string Username, string Password, string Database, int Port)
		{
			sql.hostname = Host;
			sql.username = Username;
			sql.password = Password;
			sql.database = Database;
			sql.port = Port;
		}

        public void AddEddsInfo(string Username, string Password)
        {
            edds.username = Username;
            edds.password = Password;
        }

        public void AddQbInfo(string Username, string Password)
        {
            qb.username = Username;
            qb.password = Password;
        }
		

		#endregion

		#region Public Out procedures

		/// <summary>
		/// Returns MySql info, the calling function must use th 'out' keyword in its signature
		/// example: Someobject.GetSqlInfo(out variable, out varibale2, out variable3, out varibale4)
		/// </summary>
		/// <param name="Host"></param>
		/// <param name="Username"></param>
		/// <param name="Password"></param>
		/// <param name="Database"></param>
		public void GetSqlInfo (out string Host, out string Username, out string Password, out string Database, out int Port)
		{
			Host = sql.hostname;
			Username = sql.username;
			Password = sql.password;
			Database = sql.database;
			Port = sql.port;
		}

		/// <summary>
		/// Returns Mail info, the calling function must use th 'out' keyword in its signature
		/// example: Someobject.GetMailInfo(out variable, out varibale2, out variable3, out varibale4)
		/// </summary>
		/// <param name="HostName"></param>
		/// <param name="LoginName"></param>
		/// <param name="Password"></param>
		/// <param name="Port"></param>
		public void GetMailInfo (out string HostName, out string LoginName, out string Password, out int Port)
		{
			HostName = mailhost.hostname;
			LoginName = mailhost.loginaccount;
			Password = mailhost.password;
			Port = mailhost.port;
		}
		
		/// <summary>
		/// Returns Mail info for EWS, the calling function must use th 'out' keyword in its signature
		/// </summary>
		/// <param name="LoginName"></param>
		/// <param name="Password"></param>
		public void GetMailInfo (out string LoginName, out string Password)
		{
			LoginName = mailhost.loginaccount;
			Password = mailhost.password;
		}

		/// <summary>
		/// Returns File Monitor info, the calling function must use th 'out' keyword in its signature
		/// example: Someobject.GetFileMonitorPaths(out variable, out varibale2)
		/// </summary>
		/// <param name="MonitorPath"></param>
		/// <param name="WritePath"></param>
		public void GetFileMonitorPaths (out string MonitorPath, out string WritePath)
		{
			MonitorPath = mon.monitorpath;
			WritePath = mon.writepath;
		}

		/// <summary>
		/// Returns Data host info, the calling function must use th 'out' keyword in its signature
		/// example: Someobject.GetFileMonitorPaths(out variable, out varibale2)
		/// </summary>
		/// <param name="HostName"></param>
		/// <param name="Port"></param>
		public void GetDataInfo (out string HostName, out int ServerPort, out int ClientPort)
		{
			HostName = datahost.hostname;
			ServerPort = datahost.server_port;
			ClientPort = datahost.client_port;
		}

        /// <summary>
        /// Returns Edds host info, the calling function must use the 'out' keyword in its signature
        /// example: Someobject.GetEddsInfo(out variable, out variable2)
        /// </summary>
        /// <param name="UserName"></param>        
        /// <param name="Password"></param>        
        public void GetEddsInfo(out string Username, out string Password)
        {
            Username = edds.username;
            Password = edds.password;
        }

        /// <summary>
        /// Returns Edds host info, the calling function must use the 'out' keyword in its signature
        /// example: Someobject.GetEddsInfo(out variable, out variable2)
        /// </summary>
        /// <param name="UserName"></param>        
        /// <param name="Password"></param>      
        public void GetQbInfo(out string Username, out string Password)
        {
            {
                Username = qb.username;
                Password = qb.password;
            }
        }
		#endregion

		#region Save

		/// <summary>
		/// Serializes current config settings to the specified config file in binary format.
		/// </summary>
		/// <param name="FilePath">Path where to save the file</param>
		public void SaveConfig (string FilePath)
		{
			Stream s = File.Open (FilePath, FileMode.OpenOrCreate);
			BinaryFormatter b = new BinaryFormatter ();
			b.Serialize (s, this);
			s.Close ();
		}

		/// <summary>
		/// Save the configuration to the already specified config file
		/// </summary>
		public void SaveConfig ()
		{
			SaveConfig (_configfile);
		}

		#endregion
	}
}
